package com.meilai.project.service.personnel.attendance.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.dto.personnel.attendance.OvertimeApplyDTO;
import com.meilai.project.dto.workflow.FlowBusinessDataSuperEntity;
import com.meilai.project.dto.workflow.WorkFlowCheckDTO;
import com.meilai.project.entity.personnel.attendance.LeaveApply;
import com.meilai.project.entity.personnel.attendance.OvertimeApply;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.personnel.attendance.OvertimeApplyMapper;
import com.meilai.project.service.personnel.attendance.OvertimeApplyService;
import com.meilai.project.service.workflow.WFDataService;
import com.meilai.project.util.ThreadLocalUserUtil;
import com.meilai.project.util.WorkFlowUtil;
import com.meilai.project.vo.personnel.attendance.OvertimeApplyVO;
import com.meilai.project.vo.system.UserVO;
import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;

@Service
public class OvertimeApplyServiceImpl extends ServiceImpl<OvertimeApplyMapper, OvertimeApply> implements OvertimeApplyService {
    private final static Logger logger = LoggerFactory.getLogger(OvertimeApplyServiceImpl.class);

    @Autowired
    private WFDataService wfDataService;

    @Override
    public Page<OvertimeApplyVO> selectPageList(Integer current_page, Integer page_size) {
        // 当前人
        Long userId = ThreadLocalUserUtil.get().getId();
        Page<OvertimeApplyVO> page = new Page<>(current_page, page_size);
        List<OvertimeApplyVO> list = baseMapper.selectPageList(page, userId);
        return page.setRecords(list);
    }

    @Override
    public Page<OvertimeApplyVO> checkPageList(Integer current_page, Integer page_size) {
        // 当前人
        Long userId = ThreadLocalUserUtil.get().getId();
        Page<OvertimeApplyVO> page = new Page<>(current_page, page_size);
        List<OvertimeApplyVO> list = baseMapper.checkPageList(page);

        // 设置是否需要审批
        try {
            HashMap<Long, Boolean> canCheckMap = WorkFlowUtil.canCheckData(userId, list, OvertimeApply.class);
            for (OvertimeApplyVO vo : list) {
                vo.setCanCheck(BooleanUtils.isTrue(canCheckMap.get(vo.getId())));
            }
        } catch (Exception E) {
            logger.error("需审核设置失败");
        }
        return page.setRecords(list);
    }

    @Transactional
    public boolean addOne(OvertimeApplyDTO dto) {
        // 当前人
        UserVO user = ThreadLocalUserUtil.get();
        String title = user.getName() + "提交的加班";

        // 业务数据字段
        OvertimeApply temp = new OvertimeApply();
        BeanUtils.copyProperties(dto, temp);

        // 设置流程字段，flow_type请自行对应dict_flow_type表中的id
        FlowBusinessDataSuperEntity fbdse = WorkFlowUtil.getStartSuperDataEntity(user.getId(), user.getMain_department_id(), 3, title);
        BeanUtils.copyProperties(fbdse, temp);
        // 插入业务表
        boolean flag = save(temp);
        if (!flag) throw new CommonException("新增数据失败");
        // 开始流程
        int flowResult = new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(temp.getId(), user.getId(), OvertimeApply.class)
                .Begin(0L, "", new OvertimeApply());

        if (flowResult == 1) {
            // 开始流程成功，审核后仍处于流程中
            return true;
        } else if (flowResult == 2) {
            // 流程通过
            return true;
        } else {
            throw new CommonException("开始审核流程失败");
        }
    }

    @Transactional
    public boolean adopt(OvertimeApplyDTO dto) {
        // 当前人
        Long userId = ThreadLocalUserUtil.get().getId();
        // 业务数据
        OvertimeApply tf = getById(dto.getId());
        OvertimeApply old_tf = new OvertimeApply();
        BeanUtils.copyProperties(tf, old_tf);
        // 当前审批轮次
        Long curCheckIndex = WorkFlowUtil.getCurCheckIndex(tf.getFlow_json(), dto.getNodeId());
        // 审核
        int flowResult = new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(dto.getId(), userId, OvertimeApply.class)
                .ToNext(new WorkFlowCheckDTO(dto.getNodeId(), curCheckIndex, JSONObject.toJSONString(old_tf)));
        if (flowResult == 1) {
            // 审核后仍然在流程中
            return true;
        } else if (flowResult == 2) {
            // 审核后流程通过
            return true;
        } else {
            throw new CommonException("审核失败");
        }
    }

    @Transactional
    public boolean refuse(OvertimeApplyDTO dto) {
        // 当前人
        Long userId = ThreadLocalUserUtil.get().getId();
        // 业务数据
        OvertimeApply tf = getById(dto.getId());
        OvertimeApply old_tf = new OvertimeApply();
        BeanUtils.copyProperties(tf, old_tf);
        // 当前审批轮次
        Long curCheckIndex = WorkFlowUtil.getCurCheckIndex(tf.getFlow_json(), dto.getNodeId());
        // 审核
        int flowResult = new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(dto.getId(), userId, OvertimeApply.class)
                .ReturnBack(new WorkFlowCheckDTO(dto.getNodeId(), curCheckIndex, JSONObject.toJSONString(old_tf)));
        if (flowResult == 1) {
            // 审核后流程退回
            return true;
        } else {
            throw new CommonException("审核失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(OvertimeApplyDTO dto, Long wf_data_id, boolean flag) {
        // 当前人
        UserVO user = ThreadLocalUserUtil.get();
        String title = user.getName() + "提交的加班";
        // 业务数据字段
        OvertimeApply temp = new OvertimeApply();
        BeanUtils.copyProperties(dto, temp);
        // 设置流程字段，flow_type请自行对应dict_flow_type表中的id
        FlowBusinessDataSuperEntity fbdse = WorkFlowUtil.getStartSuperDataEntity(user.getId(), user.getMain_department_id(), 3, title);
        BeanUtils.copyProperties(fbdse, temp);
        temp.setId(dto.getId());//保存ID
        boolean tmp = temp.getId() == null;
        boolean b = this.saveOrUpdate(temp);
        dto.setId(temp.getId());
        return b && (flag && tmp) ? (wf_data_id == null ? new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(temp.getId(), user.getId(), OvertimeApply.class).SaveDraft() == 1 : new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(temp.getId(), user.getId(), OvertimeApply.class).SaveDraft(wf_data_id) == 1) : true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submit(OvertimeApplyDTO dto, Long wf_data_id) {
        // 当前人
        UserVO user = ThreadLocalUserUtil.get();
        // 业务数据字段
        OvertimeApply temp = new OvertimeApply();
        BeanUtils.copyProperties(dto, temp);
        return this.save(dto, wf_data_id, false) && new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(dto.getId(), user.getId(), OvertimeApply.class).Begin(wf_data_id == null ? -1L : wf_data_id, "", temp) == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean check(Long flow_id, Long wf_data_id, Boolean isReturn, String opinion) {
        // 当前人
        Long userId = ThreadLocalUserUtil.get().getId();
        // 业务数据
        OvertimeApply tf = getById(flow_id);
        // 当前审批轮次
        Long curCheckIndex = WorkFlowUtil.getCurCheckIndex(tf.getFlow_json(), tf.getFlow_current_node_id());
        // 审核
        int flowResult = -1;
        // 审核
        if (isReturn) {
            flowResult = new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(tf.getId(), userId, OvertimeApply.class)
                    .ReturnBack(new WorkFlowCheckDTO(tf.getFlow_current_node_id(), curCheckIndex, opinion, ""));
        } else {
            flowResult = new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(tf.getId(), userId, OvertimeApply.class)
                    .ToNext(new WorkFlowCheckDTO(tf.getFlow_current_node_id(), curCheckIndex, opinion, ""));
        }
        if (flowResult == 2) {
            return true;
        } else if (flowResult == 1) {
            return true;
        } else {
            throw new CommonException("审核失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean remove(Long flow_id, Long wf_data_id) {
        Long userId = ThreadLocalUserUtil.get().getId();
        return new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(flow_id, userId, OvertimeApply.class).Delete(wf_data_id) == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean actualDelete(Long flow_id, Long wf_data_id) {
        Long userId = ThreadLocalUserUtil.get().getId();
        return new WorkFlowUtil<OvertimeApply, OvertimeApplyMapper>(flow_id, userId, OvertimeApply.class).ActualDelete(wf_data_id) == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OvertimeApplyDTO getDtoById(Long flow_id) {
        Long userId = ThreadLocalUserUtil.get().getId();
        LeaveApply data = new LeaveApply();
        OvertimeApplyDTO dto = baseMapper.getDtoById(flow_id);
        BeanUtils.copyProperties(dto, data);
        dto.setCan_check(WorkFlowUtil.canCheckData(userId, data));
        return dto;
    }
}
